package piechowicz.szymon.balloonwars;

import piechowicz.szymon.fft.*;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;

public class SpeedController
{
    
    private static final int SPEED_MAX = 50;
    private static final double INTENSITY_THRESHOLD = 100;
    private static final int FREQUENCY_THRESHOLD = 500;
    private static final int FREQUENCY_THRESHOLD_MAX = 1500;
    
    @SuppressWarnings("unused")
    private final Activity activity;
    private final SpeedControllerListener listener;
    private boolean active;
    private final int n;
    private final int samplesPerSecond;
    private final AudioRecord audioRecord;
    private final short[] buf;
    private final Complex[] bufComplex;
    private final FFT dft;
    
    public SpeedController(Activity activity, SpeedControllerListener listener)
    {
        this.activity = activity;
        this.listener = listener;
        
        samplesPerSecond = 8000;
        int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
        int minBufSize = AudioRecord.getMinBufferSize(samplesPerSecond,
                channelConfiguration,  audioEncoding);
        minBufSize >>= 1; // getMinBufferSize returns number of bytes
        int pow2 = 2;
        while (pow2 < minBufSize)
            pow2 <<= 1;
        n = pow2;
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
                samplesPerSecond, channelConfiguration, audioEncoding, n << 1);
        
        buf = new short[n];
        bufComplex = new Complex[n];
        for (int i = 0; i < n; ++i)
            bufComplex[i] = new Complex();
        dft = new FFT(n, false);
    }

    public void resume()
    {
        active = true;
        audioRecord.startRecording();
        new Thread(new Runnable()
                {
                    public void run()
                    {
                        updateLoop();
                    }
                }).start();
    }
    
    public void pause()
    {
        active = false;
        audioRecord.stop();
    }
    
    private void updateLoop()
    {
        while (active)
        {
            if (audioRecord.read(buf, 0, n) != n)
                continue;
            for (int i = 0; i < n; ++i)
                bufComplex[i].re = buf[i];
            //long x = new java.util.Date().getTime();
            Complex[] frequencies = dft.transform(bufComplex);
            //x = new java.util.Date().getTime() - x;
            // 230 ms
            //System.out.println("time: " + x);
            
            int loudestFrequency = 0;
            double loudestIntensity = INTENSITY_THRESHOLD;
            for (int k = 1; k < (n >> 1); ++k)
                if (FFT.getIntensity(frequencies[k]) > loudestIntensity)
                {
                    loudestFrequency = k * samplesPerSecond / n;
                    loudestIntensity = FFT.getIntensity(frequencies[k]);
                }
            
            listener.onSpeedChanged(getSpeed(loudestFrequency,
                    loudestIntensity));
        }
    }
    
    private int getSpeed(int f, double amp)
    {
        if (amp > INTENSITY_THRESHOLD && f > FREQUENCY_THRESHOLD)
            return SPEED_MAX * (f - FREQUENCY_THRESHOLD)
                    / (FREQUENCY_THRESHOLD_MAX - FREQUENCY_THRESHOLD);
        return 0;
    }
    
    // Classes, interfaces
    
    public interface SpeedControllerListener
    {
        
        public void onSpeedChanged(int speed);
        
    }
        
}
